home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / MTAconsole / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  49.0 KB  |  1,991 lines

  1. /* display.c : display routines */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/display.c,v 6.0 1991/12/18 20:26:48 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/display.c,v 6.0 1991/12/18 20:26:48 jpo Rel $
  9.  *
  10.  * $Log: display.c,v $
  11.  * Revision 6.0  1991/12/18  20:26:48  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include    "console.h"
  19. extern Pixmap            backpixmap;
  20. extern Mode            mode;
  21. extern int            max_horiz_mtas;
  22. extern State            connectState;
  23. extern char            *time_t2RFC(),
  24.                 *vol2str(),
  25.                 *itoa(),
  26.                 *msginfo_args[3],
  27.                 *Qinformation,
  28.                 *Qversion;
  29. extern time_t            time();
  30. void                ChanToggle(),
  31.                 MtaToggle(),
  32.                 MsgToggle();
  33. extern unsigned long        chancolourOf(),
  34.                 mtacolourOf(),
  35.                 msgcolourOf();
  36. extern XFontStruct        *chanFont(),
  37.                 *mtaFont(),
  38.                 *msgFont(),
  39.                 *normalFont,
  40.                 *disabledFont;
  41. extern Heuristic heuristic;
  42. /*   */
  43. /* channels */
  44. extern void            Channel();
  45. extern struct chan_struct    *currentchan,
  46.                 **globallist;
  47. extern Widget            channel_all,
  48.                 channels,
  49.                 channel_info,
  50.                 channel_viewport,
  51.                 channel_label,
  52.                 monitor_form,
  53.                 monitor_viewport,
  54.                 switchform,
  55.                 qversion;
  56. extern int             max_vert_lines,
  57.                 read_currentchan,
  58.                 monitor_form_managed;
  59. Widget                *channel_array = NULL;
  60. int                actual_nchans_present = 0,
  61.                 num_channels,
  62.                 chan_info_shown = FALSE;
  63. extern struct monitor_item    **display_list;
  64. extern int            compat;
  65.  
  66. static void redisplay_channel();
  67. static void monitor_display_channels();
  68. static void undisplay_monitor();
  69. static char *create_channel_display_string();
  70. static char *create_channel_monitor_string();
  71. static char *time_t2str();
  72. static void resize_info_list();
  73.  
  74. extern char        *reverse_mta(), *reverse_adr();
  75. extern int    total_volume, delta_volume,
  76.     total_number_messages, delta_messages, 
  77.     total_number_reports, delta_reports;
  78. extern Widget    total_number_label, total_volume_label;
  79. extern unsigned long    volcolourOf(), numcolourOf();
  80.  
  81. display_totals()
  82. {
  83.     char    buf[BUFSIZ], num[15];
  84.  
  85.     if (total_volume == 0
  86.         || (total_number_messages == 0
  87.         && total_number_reports == 0)) {
  88.         MapVolume(False);
  89.         return;
  90.     }
  91.     num2unit(total_volume, num);
  92.     (void) sprintf(buf, "Volume = %s", num);
  93.     if (!compat && delta_volume) {
  94.         num2unit(delta_volume, num);
  95.         (void) sprintf(buf, "%s (%s%s)",
  96.                    buf,
  97.                    (delta_volume > 0) ? "+" : "",
  98.                    num);
  99.     }
  100.  
  101.     XtVaSetValues(total_volume_label,
  102.           XtNlabel,    buf,
  103.           XtNborderColor,    volcolourOf(total_volume),
  104.           NULL);
  105.  
  106.     (void) sprintf(buf, "%d msg%s",
  107.                total_number_messages,
  108.                (total_number_messages == 1) ? "" : "s");
  109.     if (!compat && delta_messages)
  110.         (void) sprintf(buf, "%s (%s%d)",
  111.                    buf, 
  112.                    (delta_messages > 0) ? "+" : "",
  113.                    delta_messages);
  114.     (void) sprintf(buf, "%s + %d report%s", 
  115.                buf, total_number_reports,
  116.                (total_number_reports == 1) ? "" : "s");
  117.     if (!compat && delta_reports)
  118.         (void) sprintf(buf, "%s (%s%d)",
  119.                    buf,
  120.                    (delta_reports > 0) ? "+" : "",
  121.                    delta_reports);
  122.  
  123.     XtVaSetValues(total_number_label,    
  124.           XtNlabel,    buf,
  125.           XtNborderColor,    numcolourOf(total_number_messages+total_number_reports),
  126.           NULL);
  127.     MapVolume(True);
  128. }
  129.     
  130. char *create_channel_header()
  131. {
  132.     char    *str;
  133.     char    buf[BUFSIZ];
  134.     if (currentchan == NULL)
  135.         str = strdup("No current channel");
  136.     else {
  137.         sprintf(buf, "Current channel : %s : %s", 
  138.             currentchan->channelname, currentchan->channeldescrip);
  139.         str = strdup(buf);
  140.     }
  141.     return str;
  142. }
  143.  
  144. #define ssformat    "%-*s %s"
  145. #define sdformat    "%-*s %s"
  146. #define    plus_ssformat    "%s\n%-*s %s"
  147. #define plus_sdformat    "%s\n%-*s %d"
  148.  
  149. #define tab 30
  150.  
  151. extern Widget    channel_all_list;
  152.  
  153. char    *channel_info_list[100];
  154.  
  155. set_info_list(list, ix, str)
  156. char    *list[];
  157. int    ix;
  158. char    *str;
  159. {
  160.     if (list[ix]) free(list[ix]);
  161.     list[ix] = str;
  162. }
  163.  
  164. chan_display_info(chan)
  165. struct chan_struct    *chan;
  166. {
  167.     char        *str, buf[BUFSIZ];
  168.     int        ix = 0;
  169.     XFontStruct    *font;
  170.  
  171.     set_info_list(channel_info_list, ix++, strdup(chan->channelname));
  172.     set_info_list(channel_info_list, ix++, strdup(chan->channeldescrip));
  173.     if (chan->status->cachedUntil != 0)  {
  174.         set_info_list(channel_info_list, ix++, strdup("Delayed until"));
  175.         str = time_t2RFC(chan->status->cachedUntil);
  176.         set_info_list(channel_info_list, ix++, str);
  177.     }
  178.     if (chan->oldestMessage != 0 && 
  179.         (chan->numberMessages != 0 || chan->numberReports != 0)) {
  180.         set_info_list(channel_info_list, ix++, strdup("Oldest message"));
  181.         str = time_t2str(time((time_t *)0) - chan->oldestMessage);
  182.         set_info_list(channel_info_list, ix++, str);
  183.     }
  184.         
  185.     if (chan->numberMessages != 0) {
  186.         set_info_list(channel_info_list, ix++, strdup("number of messages"));
  187.         str = itoa(chan->numberMessages);
  188.         set_info_list(channel_info_list, ix++, str);
  189.     }
  190.  
  191.     if (chan->numberReports != 0) {
  192.         set_info_list(channel_info_list, ix++, strdup("number of reports"));
  193.         str = itoa(chan->numberReports);
  194.         set_info_list(channel_info_list, ix++, str);
  195.     }
  196.  
  197.     if (chan->volumeMessages != 0) {
  198.         char    num[15];
  199.         set_info_list(channel_info_list, ix++, strdup("Volume"));
  200.         num2unit(chan->volumeMessages, num);
  201.         str = strdup(num);
  202.         set_info_list(channel_info_list, ix++, str);
  203.     }
  204.         
  205.     if (chan->numberActiveProcesses != 0) {
  206.         set_info_list(channel_info_list, ix++, strdup("number of active processes"));
  207.         str = itoa(chan->numberActiveProcesses);
  208.         set_info_list(channel_info_list, ix++, str);
  209.     }
  210.  
  211.     set_info_list(channel_info_list, ix++, strdup("status"));
  212.  
  213.     set_info_list(channel_info_list, ix++, 
  214.               strdup((chan->status->enabled == TRUE) ? "enabled" : "disabled"));
  215.  
  216.     if (chan->status->lastAttempt != 0) {
  217.         set_info_list(channel_info_list, ix++, strdup("last attempt"));
  218.         str = time_t2RFC(chan->status->lastAttempt);
  219.         set_info_list(channel_info_list, ix++, str);
  220.     }
  221.  
  222.     if (chan->status->lastSuccess != 0) {
  223.         set_info_list(channel_info_list, ix++, strdup("last success"));
  224.         str = time_t2RFC(chan->status->lastSuccess);
  225.         set_info_list(channel_info_list, ix++, str);
  226.     }
  227.  
  228.     set_info_list(channel_info_list, ix++, strdup("priority"));
  229.     switch (chan->priority) {
  230.         case int_Qmgr_Priority_low:
  231.         str = strdup("low");
  232.         break;
  233.         case int_Qmgr_Priority_high:
  234.         str = strdup("high");
  235.         break;
  236.         case int_Qmgr_Priority_normal:
  237.         default:
  238.         str = strdup("normal");
  239.         break;
  240.     }
  241.     set_info_list(channel_info_list, ix++, str);
  242.  
  243.     set_info_list(channel_info_list, ix++, strdup("maximum number of processes"));
  244.     if (chan -> maxprocs == 0)
  245.         sprintf(buf, "unlimited");
  246.     else
  247.         sprintf(buf, "%d", chan->maxprocs);
  248.     set_info_list(channel_info_list, ix++, strdup(buf));
  249.  
  250.     XawListChange(channel_all_list,
  251.               channel_info_list,
  252.               ix, 0, True);
  253.  
  254.     if ((font = chanFont(chan)) != NULL)
  255.         XtVaSetValues(channel_all_list,
  256.                   XtNfont,    font,
  257.                   NULL);
  258.  
  259.     XtVaSetValues(channel_info,
  260.               XtNlabel, "all",
  261.               NULL);
  262.  
  263.     XtSetMappedWhenManaged(channel_all, True);
  264.     XtSetMappedWhenManaged(channel_viewport, False);
  265.     chan_info_shown = TRUE;
  266. }
  267.  
  268.  
  269. chan_display_all()
  270. {
  271.     XtVaSetValues(channel_info,
  272.           XtNlabel, "info",
  273.           NULL);
  274.     XtSetMappedWhenManaged(channel_viewport, True);
  275.     XtSetMappedWhenManaged(channel_all, False);
  276.     chan_info_shown = FALSE;
  277. }
  278.  
  279.  
  280. display_channels()
  281. {
  282.     clear_mta_refresh_list();
  283.     control_display_channels();
  284.     if (mode == monitor)
  285.         monitor_display_channels();
  286.     if (compat)
  287.         display_totals();
  288. }
  289.  
  290. control_display_channels()
  291. {
  292.     int            i = 0;
  293.     char            *str = NULL;
  294.     XFontStruct        *font;
  295.     for (i = 0; i < num_channels; i++)
  296.         XtSetMappedWhenManaged(channel_array[i], False);
  297.     i = 0;
  298.     while (i < num_channels) {
  299.         str = create_channel_display_string(globallist[i]);
  300.         XtVaSetValues(channel_array[i],
  301.               XtNlabel, str,
  302.               XtNborderColor, chancolourOf(globallist[i]),
  303.               XtNborderWidth, chanborderOf(globallist[i]),
  304.               XtNbackgroundPixmap, 
  305.               (globallist[i]->status->enabled == FALSE) ? backpixmap : ParentRelative,
  306.               NULL);
  307.         if ((font = chanFont(globallist[i])) != NULL)
  308.             XtVaSetValues(channel_array[i],
  309.                   XtNfont, font,
  310.                   NULL);
  311.  
  312.         free(str);
  313.         i++;
  314.     }
  315.     for (i = 0; i < num_channels; i++)
  316.         XtSetMappedWhenManaged(channel_array[i], True);
  317.     if (chan_info_shown == TRUE
  318.         && currentchan != NULL)
  319.         chan_display_info(currentchan);
  320.     if (currentchan != NULL && mode == control && read_currentchan != 0) {
  321.         clear_mta_refresh_list();
  322.         if (heuristic != chanonly) {
  323.             add_mta_refresh_list(currentchan->channelname);
  324.             construct_event(mtaread);
  325.         }
  326.     }
  327. }
  328.  
  329. /* called when channel number of msgs gets out of step with total */
  330. /* mtas number of msgs i.e. msgs go out or come in between chanread */
  331. /* and subsequent mtareads */
  332.  
  333. redisplay_control_channel(num)
  334. int    num;
  335. {
  336.     char    *str = NULL;
  337.  
  338.     XtSetMappedWhenManaged(channel_array[num], False);
  339.     str = create_channel_display_string(globallist[num]);
  340.     XtVaSetValues(channel_array[num],
  341.           XtNlabel, str,
  342.           XtNborderColor, chancolourOf(globallist[num]),
  343.           XtNborderWidth, chanborderOf(globallist[num]),
  344.           XtNbackgroundPixmap,(globallist[num]->status->enabled == FALSE) ? backpixmap : ParentRelative,
  345.           NULL);
  346.     free(str);
  347.     XtSetMappedWhenManaged(channel_array[num], True);
  348. }
  349.  
  350. static void monitor_display_channels()
  351. {
  352.     int num_displayed = 0,
  353.         i;
  354.  
  355.     order_display_channels();
  356.     XtUnmanageChild(monitor_form);
  357.     while ((num_displayed < num_channels) 
  358.            && (chanBadness(*(display_list[num_displayed]->channel)) != 0)) {
  359.         monitor_channel(num_displayed);
  360.         num_displayed++;
  361.     }
  362.     
  363.     i = num_displayed;
  364.     
  365.     while (i < num_channels
  366.            && display_list[i]->chan != NULL) {
  367.         undisplay_monitor(display_list[i]);
  368.         i++;
  369.     }
  370.     XtManageChild(monitor_form);
  371.     construct_event(mtaread);
  372. }
  373.  
  374. static void undisplay_monitor(item)
  375. struct monitor_item    *item;
  376. {
  377.     int    i = 0;
  378.     if (item->form != NULL) {
  379.         XtDestroyWidget(item->form);
  380.         item -> chan = NULL;
  381.         if (item->mtas != NULL) {
  382.             while (i < item -> num_allocd
  383.                    && item->mtas[i] != NULL) {
  384.                 item->mtas[i] = NULL;
  385.                 i++;
  386.             }
  387.         }
  388.         item->box = NULL;
  389.         item->form = NULL;
  390.     }
  391. }    
  392.  
  393. monitor_channel(num)
  394. int    num;
  395. {
  396.     
  397.     struct chan_struct    *actualchan;
  398.     int            managed = TRUE;
  399.     char            *str;
  400.     XFontStruct        *font;
  401.     /* display display_list[num] */
  402.     actualchan = *(display_list[num]->channel);
  403.     actualchan->display_num = num;
  404.  
  405.     XawFormDoLayout (monitor_form, False);
  406.  
  407.     if (connectState == connected) {
  408.         if (display_list[num]->form == NULL) {
  409.             /* need to create form */    
  410.             display_list[num]->form = XtVaCreateWidget("MonitorChannelForm",
  411.                                    formWidgetClass,
  412.                                    monitor_form,
  413.                                    XtNborderColor, chancolourOf(actualchan),
  414.                                    XtNfromVert, (num == 0) ? NULL : display_list[num-1]->form,
  415.                                    XtNfromHoriz, NULL,
  416.                                    XtNresizable, TRUE,
  417.                                    NULL);
  418.             managed = FALSE;
  419.         }
  420.         if (display_list[num]->chan != NULL) {
  421.             XtUnmanageChild(display_list[num]->chan);
  422.             str = create_channel_monitor_string(actualchan);
  423.             XtVaSetValues(display_list[num]->chan,
  424.                   XtNborderColor, chancolourOf(actualchan),
  425.                   XtNborderWidth, chanborderOf(actualchan),
  426.                   XtNlabel,     str,
  427.                   XtNbackgroundPixmap, (actualchan->status->enabled == FALSE) 
  428.                   ? backpixmap : ParentRelative,
  429.                   NULL);
  430.             if ((font = chanFont(actualchan)) != NULL)
  431.                 XtVaSetValues(display_list[num]->chan,
  432.                       XtNfont,    font,
  433.                       NULL);
  434.  
  435.             XtManageChild(display_list[num]->chan);
  436.             free(str);
  437.         } else {
  438.             str = create_channel_monitor_string(actualchan);
  439.             display_list[num]->chan =
  440.                 XtVaCreateManagedWidget("MonitorChannel",
  441.                             labelWidgetClass,
  442.                             display_list[num]->form,
  443.                             XtNresizable, TRUE,
  444.                             XtNborderColor, chancolourOf(actualchan),
  445.                             XtNborderWidth, chanborderOf(actualchan),
  446.                             XtNlabel, str,
  447.                             XtNbackgroundPixmap, (actualchan->status->enabled == FALSE) 
  448.                             ? backpixmap : ParentRelative,
  449.                             XtNfromVert, NULL,
  450.                             XtNfromHoriz, NULL,
  451.                             XtNleft,    XtChainLeft,
  452.                             XtNright,    XtChainLeft,
  453.                             XtNtop,    XtChainTop,
  454.                             XtNbottom,    XtChainTop,
  455.                             XtNjustify, XtJustifyRight,
  456.                             NULL);
  457.             if ((font = chanFont(actualchan)) != NULL)
  458.                 XtVaSetValues(display_list[num]->chan,
  459.                       XtNfont,    font,
  460.                       NULL);
  461.             free(str);
  462.  
  463.         }
  464.         if (managed == FALSE)
  465.             XtManageChild(display_list[num]->form);
  466.         XawFormDoLayout(display_list[num]->form, False);
  467.         XtVaSetValues(display_list[num]->form,
  468.               XtNborderColor, chancolourOf(actualchan),
  469.               NULL);
  470.         if (heuristic != chanonly
  471.             && (actualchan->numberMessages > 0 
  472.             || actualchan->numberReports > 0
  473.             || actualchan->volumeMessages > 0))
  474.             add_mta_refresh_list(actualchan->channelname);
  475.     }
  476.     if (display_list[num]->box != NULL)
  477.         XtUnmanageChild(display_list[num]->box);
  478.     XawFormDoLayout(display_list[num]->form, True);
  479.     XawFormDoLayout(monitor_form, True);
  480. }
  481.  
  482. static char *create_channel_display_string(chan)
  483. struct chan_struct    *chan;
  484. {
  485.     char    str[BUFSIZ];
  486.  
  487.     sprintf(str,"%s",chan->channelname);
  488.     if (chan -> numberActiveProcesses > 1)
  489.         sprintf(str, "%s (%d)",
  490.             str, chan->numberActiveProcesses);
  491.     sprintf(str,"%s: %d",
  492.         str,chan->numberMessages);
  493.     if (chan->numberReports != 0)
  494.       sprintf(str,"%s + %d", str, chan->numberReports);
  495.     if (chan->given_num_mtas != 0)
  496.         sprintf(str,"%s/%d",str, chan->given_num_mtas);
  497.     return strdup(str);
  498. }
  499.  
  500. static char *create_channel_monitor_string(chan)
  501. struct chan_struct    *chan;
  502. {
  503.     char    str[BUFSIZ];
  504.  
  505.     sprintf(str,"%s : %d %s",
  506.         chan->channelname,
  507.         chan->numberMessages,
  508.         (chan->numberMessages == 1) ? "msg" : "msgs");
  509.  
  510.     if (chan->numberReports != 0)
  511.         sprintf(str, "%s and %d %s",
  512.           str,
  513.           chan->numberReports,
  514.           (chan->numberReports == 1) ? "DR" : "DRs");
  515.  
  516.     sprintf(str, "%s on %d %s",
  517.         str,
  518.         chan->given_num_mtas,
  519.         (chan->given_num_mtas == 1) ? "mta" : "mtas");
  520.  
  521.     if (chan -> numberActiveProcesses > 0) {
  522.         sprintf (str, "%s, %d process%s active", str,
  523.              chan -> numberActiveProcesses,
  524.              chan -> numberActiveProcesses > 1 ? "es" : "");
  525.     }
  526.  
  527.     if (chan->deltaMessages || chan->deltaReports || 
  528.         chan->deltaMtas || chan->deltaVolume) {
  529.         sprintf(str, "%s, net change:", str);
  530.         if (chan->deltaMessages)
  531.             sprintf(str, "%s %s%d msg%s", str,
  532.                 (chan->deltaMessages > 0) ? "+" : "",
  533.                 chan->deltaMessages, (chan->deltaMessages == 1 || chan->deltaMessages == -1) ? "" : "s");
  534.         if (chan->deltaReports)
  535.             sprintf(str, "%s %s%d report%s", str,
  536.                 (chan->deltaReports > 0) ? "+" : "",
  537.                 chan->deltaReports, (chan->deltaReports == 1 || chan->deltaReports == -1) ? "" : "s");
  538.         if (chan->deltaMtas)
  539.             sprintf(str, "%s %s%d mta%s", str,
  540.                 (chan->deltaMtas > 0) ? "+" : "",
  541.                 chan->deltaMtas, (chan->deltaMtas == 1 || chan->deltaMtas == -1) ? "" : "s");
  542.  
  543.         if (chan->deltaVolume) {
  544.             char    num[15];
  545.             num2unit(chan->deltaVolume, num);
  546.             sprintf(str, "%s (%s%s)", str,
  547.                 (chan->deltaVolume > 0) ? "+" : "",
  548.                 num);
  549.         }
  550.     }
  551.     return strdup(str);
  552. }
  553.  
  554. resize_chan_array(num)
  555. int    num;    /* number of channels that will be displayed */
  556. {
  557.     int    i = num;
  558.     char    *str;
  559.  
  560.     XtSetMappedWhenManaged(channels, False); 
  561.     while (i < actual_nchans_present) {
  562.         XtUnmanageChild(channel_array[i]);
  563.         i++;
  564.     }
  565.     
  566.     XSync(XtDisplay(channels), False);
  567.  
  568.     i = num;
  569.     while (i < actual_nchans_present) {
  570.         XtDestroyWidget(channel_array[i]);
  571.         i++;
  572.     }
  573.  
  574.     if (num == 0) {
  575.         if (channel_array != NULL) {
  576.             free ((char *) channel_array);
  577.             channel_array = NULL;
  578.         }
  579.     } else if (actual_nchans_present == 0)
  580.         /* haven't got any so malloc first lot */
  581.         channel_array = (Widget *) calloc((unsigned) num, 
  582.                           sizeof(Widget));
  583.     else if (actual_nchans_present != num)
  584.         /* need some more */
  585.         channel_array = (Widget *) realloc((char *) channel_array, 
  586.                            (unsigned) (num * sizeof(Widget)));
  587.     while (actual_nchans_present < num) {
  588.         str = itoa(actual_nchans_present);
  589.         channel_array[actual_nchans_present] = 
  590.             XtVaCreateManagedWidget(NULL,
  591.                      labelWidgetClass,
  592.                      channels,
  593.                      XtNborderWidth,    2,
  594.                      XtNlabel, str,
  595.                      NULL);
  596.         actual_nchans_present++;
  597.         free(str);
  598.     }
  599.     actual_nchans_present = num;
  600.     XtSetMappedWhenManaged(channels, True); 
  601. }
  602.  
  603. /*   */
  604. /* mtas */
  605. extern struct mta_struct    *currentmta;
  606. extern int            read_currentmta;
  607. extern int            max_mta_border;
  608. extern void            Mta();
  609. extern Widget            mtas,
  610.                 mta_all,
  611.                 mta_all_list,
  612.                 mta_info,
  613.                 mta_viewport,
  614.                 mta_label;
  615.  
  616. struct mta_disp_struct        *mta_array = NULL;
  617. int                actual_nmtas_present = 0,
  618.                 num_mtas_displayed = 0,
  619.                 mta_info_shown = FALSE;
  620. static char            *create_mta_display_string();
  621. extern int            mta_info_strlen;
  622. extern int            uk_order;
  623.  
  624. char    *mta_info_list[100];
  625.  
  626. mta_display_info(chan,mta)
  627. struct chan_struct    *chan;
  628. struct mta_struct    *mta;
  629. {
  630.     char        *str;
  631.     char        buf[BUFSIZ];
  632.     int        ix = 0;
  633.     XFontStruct    *font;
  634.  
  635.     str = (uk_order) ? reverse_mta(mta->mta) : strdup(mta->mta);
  636.     set_info_list(mta_info_list, ix++, str);
  637.     
  638.     sprintf(buf, "on channel '%s'", chan->channelname);
  639.     set_info_list(mta_info_list, ix++, strdup(buf));
  640.  
  641.     if (mta->status->cachedUntil != 0) {
  642.         set_info_list(mta_info_list, ix++, strdup("Delayed until"));
  643.         str = time_t2RFC(mta->status->cachedUntil);
  644.         set_info_list(mta_info_list, ix++, str);
  645.     }
  646.  
  647.     if (mta->info != NULLCP) {
  648.         set_info_list(mta_info_list, ix++, strdup("Error Information"));
  649.         set_info_list(mta_info_list, ix++, strdup(mta->info));
  650.     }
  651.               
  652.     set_info_list(mta_info_list, ix++, strdup("Oldest message"));
  653.     str = time_t2str(time((time_t *) 0) - mta->oldestMessage);
  654.     set_info_list(mta_info_list, ix++, str);
  655.  
  656.     if (mta->numberMessages != 0) {
  657.         set_info_list(mta_info_list, ix++, strdup("Number of messages"));
  658.         str = itoa(mta->numberMessages);
  659.         set_info_list(mta_info_list, ix++, str);
  660.     }
  661.     if (mta->numberReports != 0) {
  662.         set_info_list(mta_info_list, ix++, strdup("Number of reports"));
  663.         str = itoa(mta->numberReports);
  664.         set_info_list(mta_info_list, ix++, str);
  665.     }
  666.  
  667.     set_info_list(mta_info_list, ix++, strdup("Volume"));
  668.     str = vol2str(mta->volumeMessages);
  669.     set_info_list(mta_info_list, ix++, str);
  670.  
  671.     if (mta -> active) {
  672.         set_info_list(mta_info_list, ix++, strdup("active"));
  673.         set_info_list(mta_info_list, ix++, strdup("processes running"));
  674.     }
  675.     
  676.     set_info_list(mta_info_list, ix++, strdup("Status"));
  677.     set_info_list(mta_info_list, ix++,
  678.               strdup((mta->status->enabled == TRUE) ? "enabled" : "disabled"));
  679.  
  680.     if (mta->status->lastAttempt != 0) {
  681.         set_info_list(mta_info_list, ix++, strdup("Last attempt"));
  682.         str = time_t2RFC(mta->status->lastAttempt);
  683.         set_info_list(mta_info_list, ix++, str);
  684.     }
  685.  
  686.     if (mta->status->lastSuccess != 0) {
  687.         set_info_list(mta_info_list, ix++, strdup("Last success"));
  688.         str = time_t2RFC(mta->status->lastSuccess);
  689.         set_info_list(mta_info_list, ix++, str);
  690.     }
  691.  
  692.     set_info_list(mta_info_list, ix++, strdup("Priority"));
  693.     switch (mta->priority) {
  694.         case int_Qmgr_Priority_low:
  695.         str = strdup("low");
  696.         break;
  697.         default:
  698.         case int_Qmgr_Priority_normal:
  699.         str = strdup("normal");
  700.         break;
  701.         case int_Qmgr_Priority_high:
  702.         str = strdup("high");
  703.         break;
  704.     }
  705.     set_info_list(mta_info_list, ix++, str);
  706.  
  707.     XawListChange(mta_all_list,
  708.               mta_info_list,
  709.               ix, 0, True);
  710.  
  711.     if ((font = mtaFont(mta)) != NULL)
  712.         XtVaSetValues(mta_all_list,
  713.                   XtNfont, font,
  714.                   NULL);
  715.  
  716.     XtVaSetValues(mta_info,
  717.           XtNlabel, "all",
  718.           NULL);
  719.     XtSetMappedWhenManaged(mta_all, True);
  720.     XtSetMappedWhenManaged(mta_viewport, False);
  721.     mta_info_shown = TRUE;
  722. }
  723.  
  724. mta_display_all()
  725. {
  726.     XtVaSetValues(mta_info,
  727.           XtNlabel, "info",
  728.           NULL);
  729.     XtSetMappedWhenManaged(mta_viewport, True);
  730.     XtSetMappedWhenManaged(mta_all, False);
  731.     mta_info_shown = FALSE;
  732. }
  733.  
  734. display_empty_mta_list(chan)
  735. struct chan_struct    *chan;
  736. {
  737.     /* reset counters */
  738.     if (chan != NULL && chan->mtalist != NULL)
  739.         free_mta_list(&(chan->mtalist), &(chan->num_mtas));
  740.     XtUnmanageChild(mtas);
  741.     XtSetMappedWhenManaged(mtas, False);
  742.     resize_mta_array(0);
  743.     XtSetMappedWhenManaged(mtas, True);
  744.     XtManageChild(mtas);
  745.     reset_label(mta_label);
  746.     MtaToggle();
  747.     MsgToggle();
  748. }
  749.     
  750. display_mtas(chan)
  751. struct chan_struct    *chan;
  752. {
  753.     if (mode == monitor)
  754.         monitor_display_mtas(chan);
  755.     else
  756.         control_display_mtas(chan);
  757. }
  758.  
  759. control_display_mtas(chan)
  760. struct    chan_struct    *chan;
  761. {
  762.     int    i;
  763.     char    *str;
  764.     XFontStruct    *font;
  765.  
  766.     XtSetMappedWhenManaged(mtas, False);
  767.     XtUnmanageChild(mtas);
  768.  
  769.     resize_mta_array(chan->num_mtas);
  770.  
  771.     i = 0;
  772.     while (i < num_mtas_displayed) {
  773.         mta_array[i].mta = chan->mtalist[i];
  774.         str = create_mta_display_string(mta_array[i].mta);
  775.         XtSetMappedWhenManaged(mta_array[i].widget, True);
  776.         XtUnmanageChild(mta_array[i].widget);
  777.         XtVaSetValues(mta_array[i].widget,
  778.               XtNlabel, str,
  779.               XtNborderColor, mtacolourOf(mta_array[i].mta),
  780.               XtNborderWidth, mtaborderOf(mta_array[i].mta),
  781.               XtNfromVert, (i == 0) ? NULL : mta_array[i-1].widget,
  782.               XtNbackgroundPixmap,
  783.               (mta_array[i].mta->status->enabled == FALSE) ? backpixmap : ParentRelative,
  784.               NULL);
  785.         if ((font = mtaFont(mta_array[i].mta)) != NULL)
  786.             XtVaSetValues(mta_array[i].widget,
  787.                   XtNfont, font,
  788.                   NULL);
  789.  
  790.         XtManageChild(mta_array[i].widget);
  791.         free(str);
  792.         i++;
  793.     }
  794.     if (mta_info_shown == TRUE
  795.         && currentchan != NULL
  796.         && currentmta != NULL)
  797.         mta_display_info(currentchan, currentmta);
  798.     if (currentchan != NULL
  799.         && read_currentmta != 0
  800.         && currentmta != NULL) {
  801.         msginfo_args[0] = currentchan->channelname;
  802.         msginfo_args[1] = currentmta->mta;
  803.         if (is_loc_chan(currentchan) == TRUE)
  804.             /* local */
  805.             msginfo_args[2] = (char *) 1;
  806.         else
  807.             msginfo_args[2] = (char *) 0;
  808.         construct_event(readchannelmtamessage);
  809.     } else 
  810.         display_empty_msg_list();
  811.     XtManageChild(mtas);
  812.     XtSetMappedWhenManaged(mtas, True);
  813. }
  814.  
  815. int    oldnum;
  816. extern int    percent,
  817.         lower_bound_mtas;
  818.  
  819. static void resize_and_zero (pbuf, pnum, num, size)
  820. char    **pbuf;
  821. int    *pnum;
  822. int    num;
  823. unsigned size;
  824. {
  825.     if (*pbuf == NULLCP)
  826.         *pbuf = calloc((unsigned)num, size);
  827.     else {
  828.         *pbuf = realloc(*pbuf,
  829.                 (unsigned) (num * size));
  830.         if (num > *pnum)
  831.             bzero (((*pbuf) + (*pnum)*size),
  832.                    (unsigned) (num-(*pnum))*size);
  833.     }
  834.     *pnum = num;
  835. }
  836.             
  837.  
  838.         
  839. monitor_display_mtas(chan)
  840. struct chan_struct    *chan;
  841. {
  842.     int     num_displayed = 0,
  843.         line_num = 0,
  844.         bigestBorderWidth = 0, horiz;
  845.     int    max_allowed, num_alloced;
  846.     int num_vert_lines = 0, max_num;
  847.  
  848.     Dimension    vp_len, chan_len, dist, longest_len,
  849.             line_len = 0;
  850.     Widget        abovewidget = NULL;
  851.     int        temp;
  852.  
  853.     XawFormDoLayout(monitor_form, False);
  854.     XawFormDoLayout(display_list[chan->display_num]->form, False);
  855.     XtVaSetValues(monitor_form,
  856.           XtNleft,    XtRubber,
  857.           XtNright,    XtRubber,
  858.           XtNtop,    XtRubber,
  859.           XtNbottom,    XtRubber,
  860.           NULL);
  861.     XtVaSetValues(display_list[chan->display_num]->form,
  862.           XtNleft,    XtRubber,
  863.           XtNright,    XtRubber,
  864.           XtNtop,    XtRubber,
  865.           XtNbottom,    XtRubber,
  866.           NULL);
  867.  
  868.     if (display_list[chan->display_num]->box == NULL) {
  869.         display_list[chan->display_num]->box =
  870.             XtVaCreateWidget("MonitorMTAForm",
  871.                      formWidgetClass,
  872.                      display_list[chan->display_num]->form,
  873.                      XtNresizable,    TRUE,
  874.                      XtNborderWidth,    0,
  875.                      XtNfromHoriz,    NULL,
  876.                      XtNfromVert,    display_list[chan->display_num]->chan,
  877.                      XtNbackgroundPixmap, ParentRelative,
  878.                      XtNvertDistance,    0,
  879.                      NULL);
  880.     }
  881.     XtVaSetValues(display_list[chan->display_num]->box,
  882.           XtNleft,    XtRubber,
  883.           XtNright,    XtRubber,
  884.           XtNtop,    XtRubber,
  885.           XtNbottom,    XtRubber,
  886.           NULL);
  887.  
  888.     XawFormDoLayout(display_list[chan->display_num]->box, False);
  889.  
  890.     XtVaGetValues(switchform,
  891.               XtNwidth,    &vp_len,
  892.               NULL);
  893.     XtVaGetValues(display_list[chan->display_num]->chan,
  894.               XtNwidth,    &chan_len,
  895.               NULL);
  896.     XtVaGetValues(display_list[chan->display_num]->form,
  897.               XtNdefaultDistance, &temp,
  898.               NULL);
  899.     XtVaGetValues(display_list[chan->display_num]->box,
  900.               XtNhorizDistance,    &horiz,
  901.               NULL);
  902.     dist = (Dimension) temp;
  903.     longest_len = vp_len-3*dist-horiz-20;
  904.     /* -20 is fudge for scrollbar */
  905.  
  906.     switch (heuristic) {
  907.         case chanonly:
  908.         break;
  909.         case percentage:
  910.         max_allowed = (chan->num_mtas * chanBadness(chan) * percent) / (max_bad_channel * 100);
  911.         num_alloced = (max_allowed < lower_bound_mtas) ? lower_bound_mtas : max_allowed;
  912.  
  913.         if (display_list[chan->display_num]->num_allocd < num_alloced)
  914.             resize_and_zero (&(display_list[chan->display_num]->mtas),
  915.                      &display_list[chan->display_num]->num_allocd,
  916.                      num_alloced,
  917.                      sizeof(Mta_disp_struct *));
  918.                
  919.         while (num_displayed < chan->num_mtas
  920.                && mtaBadness(chan->mtalist[num_displayed]) != 0
  921.                && (num_displayed < lower_bound_mtas
  922.                || num_displayed < max_allowed)) {
  923.             if (monitor_mta(chan->display_num, 
  924.                     chan->mtalist[num_displayed], 
  925.                     num_displayed,
  926.                     &line_num,
  927.                     &line_len,
  928.                     &abovewidget,
  929.                     longest_len,
  930.                     dist,
  931.                     max_allowed,
  932.                     &bigestBorderWidth) == OK)
  933.                 num_displayed++;
  934.         }
  935.         break;
  936.         case line:
  937.         num_vert_lines = NumVertLines(chan);
  938.         if (num_vert_lines <= 0) num_vert_lines = 1;
  939.         max_num = num_vert_lines * max_horiz_mtas;
  940.         if (max_num == 0) max_num++;
  941.  
  942.         if (display_list[chan->display_num]->num_allocd < max_num) 
  943.             resize_and_zero(&(display_list[chan->display_num]->mtas),
  944.                     &(display_list[chan->display_num]->num_allocd),
  945.                     max_num,
  946.                     sizeof(Mta_disp_struct *));
  947.  
  948.         while (num_displayed < max_num 
  949.                && line_num < num_vert_lines
  950.                && (num_displayed < chan->num_mtas)
  951.                && (mtaBadness(chan->mtalist[num_displayed]) != 0)) {
  952.             if (monitor_mta(chan->display_num, 
  953.                     chan->mtalist[num_displayed], 
  954.                     num_displayed,
  955.                     &line_num,
  956.                     &line_len,
  957.  
  958.                     &abovewidget,
  959.                     longest_len,
  960.                     dist,
  961.                     num_vert_lines, 
  962.                     &bigestBorderWidth) == OK)
  963.                 num_displayed++;
  964.         }
  965.         break;
  966.         case all:
  967.         if (display_list[chan->display_num]->num_allocd <
  968.             chan->num_mtas) 
  969.             resize_and_zero(&(display_list[chan->display_num]->mtas),
  970.                     &(display_list[chan->display_num]->num_allocd),
  971.                     chan->num_mtas,
  972.                     sizeof(Mta_disp_struct *));
  973.  
  974.         while (num_displayed < chan->num_mtas
  975.                && mtaBadness(chan->mtalist[num_displayed]) != 0) {
  976.             if (monitor_mta(chan->display_num, 
  977.                     chan->mtalist[num_displayed], 
  978.                     num_displayed,
  979.                     &line_num,
  980.                     &line_len,
  981.  
  982.                     &abovewidget,
  983.                     longest_len,
  984.                     dist,
  985.                     num_vert_lines, 
  986.                     &bigestBorderWidth) == OK)
  987.                 num_displayed++;
  988.         }
  989.         break;
  990.     }
  991.             
  992.                              
  993.     oldnum = display_list[chan->display_num]->num_mtas;
  994.  
  995.     display_list[chan->display_num]->num_mtas = num_displayed;
  996.     
  997.     while (num_displayed < display_list[chan->display_num] -> num_allocd
  998.            && display_list[chan->display_num]->mtas[num_displayed] != NULL
  999.            && display_list[chan->display_num]->mtas[num_displayed]->widget != NULL) {
  1000.         undisplay_mta_monitor(&(display_list[chan->display_num]->mtas[num_displayed]->widget));
  1001.         num_displayed++;
  1002.     }
  1003.  
  1004.     if (display_list[chan->display_num]->num_mtas == 0) {
  1005.         undisplay_mta_monitor(&(display_list[chan->display_num]->box));
  1006.         XawFormDoLayout(display_list[chan->display_num]->form, True);
  1007.         XtVaSetValues(display_list[chan->display_num]->form,
  1008.               XtNleft,    XtChainLeft,
  1009.               XtNright,    XtChainLeft,
  1010.               XtNtop,    XtChainTop,
  1011.               XtNbottom,    XtChainTop,
  1012.               NULL);
  1013.         XawFormDoLayout(monitor_form, True);
  1014.         XtVaSetValues(monitor_form,
  1015.               XtNleft,    XtChainLeft,
  1016.               XtNright,    XtChainLeft,
  1017.               XtNtop,    XtChainTop,
  1018.               XtNbottom,    XtChainTop,
  1019.               NULL);
  1020.         return;
  1021.     }
  1022.     XawFormDoLayout(display_list[chan->display_num]->box, True);
  1023.     
  1024.     XtManageChild(display_list[chan->display_num]->box);
  1025.     XtVaSetValues(display_list[chan->display_num]->box,
  1026.           XtNleft,    XtChainLeft,
  1027.           XtNright,    XtChainLeft,
  1028.           XtNtop,    XtChainTop,
  1029.           XtNbottom,    XtChainTop,
  1030.           NULL);
  1031.     XawFormDoLayout(display_list[chan->display_num]->form, True);
  1032.     XtVaSetValues(display_list[chan->display_num]->form,
  1033.           XtNleft,    XtChainLeft,
  1034.           XtNright,    XtChainLeft,
  1035.           XtNtop,    XtChainTop,
  1036.           XtNbottom,    XtChainTop,
  1037.           NULL);
  1038.     XawFormDoLayout(monitor_form, True);
  1039.     XtVaSetValues(monitor_form,
  1040.           XtNleft,    XtChainLeft,
  1041.           XtNright,    XtChainLeft,
  1042.           XtNtop,    XtChainTop,
  1043.           XtNbottom,    XtChainTop,
  1044.           NULL);
  1045. }
  1046.  
  1047. undisplay_mta_monitor(pwidget)
  1048. Widget    *pwidget;
  1049. {
  1050.     if (*pwidget != NULL) {
  1051. /*        XtDestroyWidget(*pwidget);
  1052.         *pwidget = NULL;
  1053. */
  1054.         if (XtIsManaged (*pwidget))
  1055.             XtUnmanageChild (*pwidget);
  1056.     }
  1057. }
  1058.  
  1059. monitor_mta(chan_display_num,
  1060.         mta, 
  1061.         num, 
  1062.         pline_num,
  1063.         pline_len,
  1064.         pvert,
  1065.         longest,
  1066.         dist,
  1067.         linesAllowed,
  1068.         borderWidth_ub)
  1069. int            chan_display_num;
  1070. struct mta_struct    *mta;
  1071. int            num;
  1072. int            *pline_num;
  1073. Dimension        *pline_len;
  1074. Widget            *pvert;
  1075. Dimension        longest,
  1076.             dist;
  1077. int            linesAllowed;
  1078. int            *borderWidth_ub;
  1079. {
  1080.     char    *str;
  1081.     Widget    horiz = NULL;
  1082.     Widget *w;
  1083.     Dimension    widget_width;
  1084.     Dimension    borderWidth = mtaborderOf(mta);
  1085.     XFontStruct    *font;
  1086.  
  1087.     str = create_mta_display_string(mta);
  1088.     
  1089.     if (display_list[chan_display_num]->mtas[num] == NULL)
  1090.         /* need to create widget */
  1091.         display_list[chan_display_num]->mtas[num] = 
  1092.             (Mta_disp_struct *) calloc(1, sizeof(Mta_disp_struct));
  1093.  
  1094.     display_list[chan_display_num]->mtas[num]->mta = mta;
  1095.  
  1096.     w = &display_list[chan_display_num]->mtas[num]->widget;
  1097.     if (*w == NULL) {
  1098.         *w = XtVaCreateManagedWidget("MonitorMTA",
  1099.                          labelWidgetClass,
  1100.                          display_list[chan_display_num] ->box,
  1101.                          XtNresizable,    TRUE,
  1102.                          XtNborderWidth,    borderWidth,
  1103.                          XtNlabel, str,
  1104.                          XtNborderColor, mtacolourOf(mta),
  1105.                          XtNbackgroundPixmap,
  1106.                          (mta->status->enabled == FALSE) ? backpixmap : ParentRelative,
  1107.                          XtNleft,    XtChainLeft,
  1108.                          XtNright,    XtChainLeft,
  1109.                          XtNtop,    XtChainTop,
  1110.                          XtNbottom,    XtChainTop,
  1111.                          NULL);
  1112.     } else {
  1113.         XtVaSetValues (*w,
  1114.                    XtNborderWidth,    borderWidth,
  1115.                    XtNlabel, str,
  1116.                    XtNborderColor, mtacolourOf(mta),
  1117.                    XtNbackgroundPixmap,
  1118.                    (mta->status->enabled == FALSE ?
  1119.                 backpixmap : ParentRelative),
  1120.                    NULL);
  1121.     }
  1122.     free(str);
  1123.     
  1124.     if ((font = mtaFont(mta)) != NULL)
  1125.         XtVaSetValues(*w,
  1126.                   XtNfont,  font,
  1127.                   NULL);
  1128.  
  1129.     XtVaGetValues(*w,
  1130.               XtNwidth,    &widget_width,
  1131.               NULL);
  1132.  
  1133.     if (*pline_len+dist+widget_width > longest) {
  1134.         /* new line */
  1135.         (*pline_num)++;
  1136.         if (heuristic == line && (*pline_num) >= linesAllowed) {
  1137.             undisplay_mta_monitor(w);
  1138.             return NOTOK;
  1139.         }
  1140.         if (num == 0) /* problems ? */
  1141.             *pvert = NULL;
  1142.         else
  1143.             *pvert = display_list[chan_display_num]->
  1144.                 mtas[num-1]->widget;
  1145.         horiz = NULL;
  1146.         (*pline_len) = dist+widget_width;
  1147.     } else {
  1148.         if (num == 0)
  1149.             horiz = NULL;
  1150.         else
  1151.             horiz = display_list[chan_display_num]->
  1152.                 mtas[num-1]->widget;
  1153.         (*pline_len) += dist+widget_width;
  1154.     }
  1155.  
  1156.     XtVaSetValues(*w,
  1157.               XtNfromVert,    *pvert,
  1158.               XtNfromHoriz,    horiz,
  1159.               NULL);
  1160.     if (!XtIsManaged (*w))
  1161.         XtManageChild(*w);
  1162.     if ((int) borderWidth > *borderWidth_ub)
  1163.         *borderWidth_ub = borderWidth;
  1164.     return OK;
  1165. }
  1166.  
  1167. char    *create_mta_header()
  1168. {
  1169.     /* takes from current channel and current mta */
  1170.     char    *str;
  1171.     char    *ch;
  1172.     char    buf[BUFSIZ];
  1173.     if (currentmta == NULL
  1174.         || currentchan == NULL)
  1175.         str = strdup("No current mta");
  1176.     else {
  1177.         ch = (uk_order) ? 
  1178.             reverse_mta(currentmta -> mta) : currentmta -> mta;
  1179.         sprintf(buf, "Current mta : %s on %s", 
  1180.             ch, currentchan->channelname);
  1181.         if (uk_order && ch != currentmta -> mta) free(ch);
  1182.         str = strdup(buf);
  1183.     }
  1184.  
  1185.     return str;
  1186. }
  1187.  
  1188. static char *create_mta_display_string(mta)
  1189. struct mta_struct    *mta;
  1190. {
  1191.     char    str[BUFSIZ];
  1192.     char    *ch;
  1193.  
  1194.     ch = (uk_order)? reverse_mta(mta->mta) : mta->mta;
  1195.     sprintf(str, "%s : %d",ch, mta->numberMessages);
  1196.     if (uk_order && ch != mta->mta) free(ch);
  1197.     if (mta->numberReports != 0)
  1198.       sprintf(str, "%s + %d", str, mta->numberReports);
  1199.     return strdup(str);
  1200. }
  1201.  
  1202. resize_mta_array(num)
  1203. int    num;    /* new number of mtas */
  1204. {
  1205.  
  1206.     int    i = num;
  1207.  
  1208.     while (i < actual_nmtas_present) {
  1209.         XtSetMappedWhenManaged(mta_array[i].widget, False);
  1210.         XtUnmanageChild(mta_array[i].widget);
  1211.         XtDestroyWidget(mta_array[i].widget);
  1212.         i++;
  1213.     }
  1214.     if (num == 0) {
  1215.         if (mta_array != NULL) {
  1216.             free((char *) mta_array);
  1217.             mta_array = NULL;
  1218.         }
  1219.     } else if (actual_nmtas_present == 0)
  1220.         mta_array = (struct mta_disp_struct *)
  1221.             calloc((unsigned int) num,
  1222.                    sizeof(struct mta_disp_struct));
  1223.     else if (num != actual_nmtas_present)
  1224.         mta_array = (struct mta_disp_struct *)
  1225.             realloc((char *) mta_array,
  1226.                 (unsigned int) (num * sizeof(struct mta_disp_struct)));
  1227.     while (actual_nmtas_present < num) {
  1228.         mta_array[actual_nmtas_present].mta = NULL;
  1229.         mta_array[actual_nmtas_present].widget =
  1230.             XtVaCreateManagedWidget(NULL,
  1231.                      labelWidgetClass,
  1232.                      mtas,
  1233.                      XtNresizable,    TRUE,
  1234.                      XtNleft,    XtChainLeft,
  1235.                      XtNright,    XtChainLeft,
  1236.                      XtNtop,    XtChainTop,
  1237.                      XtNbottom,    XtChainTop,
  1238.                      XtNborderWidth,    2,
  1239.                      NULL);
  1240.         actual_nmtas_present++;
  1241.     }
  1242.     actual_nmtas_present = num;
  1243.     num_mtas_displayed = num;
  1244. }
  1245.  
  1246. /*   */
  1247. /* msgs */
  1248. extern struct msg_struct    *currentmsg,
  1249.                 **global_msg_list;
  1250. extern int            max_msg_border;
  1251. extern void            Msg();
  1252. extern Widget            msg_all,
  1253.                 msg_all_list,
  1254.                 msgs,
  1255.                 msg_info,
  1256.                 msg_viewport,
  1257.                 msg_label;
  1258. extern int                   number_msgs,
  1259.                 msg_info_strlen;
  1260.  
  1261. struct msg_disp_struct        *msg_array = NULL;
  1262. int                actual_nmsgs_present = 0,
  1263.                 num_msgs_displayed = 0,
  1264.                 msg_info_shown = FALSE;
  1265. static char            *create_msg_display_string();
  1266.  
  1267. char    **msg_info_list;
  1268. int    msg_info_list_size = 0;
  1269.  
  1270. msg_display_info(msg)
  1271. struct msg_struct    *msg;
  1272. {
  1273.     struct recip    *ix;
  1274.     char        *str, buf[BUFSIZ];
  1275.     XFontStruct    *font;
  1276.     int        i = 0;
  1277.  
  1278.     if (msg_info_list_size == 0) 
  1279.         resize_info_list(&msg_info_list, &msg_info_list_size);
  1280.  
  1281.     set_info_list(msg_info_list, i++, strdup(msg->msginfo->queueid));
  1282.     set_info_list(msg_info_list, i++, strdup(" "));
  1283.  
  1284.     set_info_list(msg_info_list, i++, strdup("Originator"));
  1285.     str = (uk_order) ? reverse_adr(msg->msginfo->originator) 
  1286.         : strdup(msg->msginfo->originator);
  1287.     set_info_list(msg_info_list, i++, str);
  1288.  
  1289.     if (msg->msginfo->size != 0) {
  1290.         set_info_list(msg_info_list, i++, strdup("Size"));
  1291.         num2unit(msg->msginfo->size, buf);
  1292.         set_info_list(msg_info_list, i++, strdup(buf));
  1293.     }
  1294.     if (msg->msginfo->uaContentId != NULLCP) {
  1295.         set_info_list(msg_info_list, i++, strdup("UA content ID"));
  1296.         set_info_list(msg_info_list, i++, strdup(msg->msginfo->uaContentId));
  1297.     }
  1298.  
  1299.     if (msg->msginfo->inChannel != NULLCP) {
  1300.         set_info_list(msg_info_list, i++, strdup("Inbound channel"));
  1301.         set_info_list(msg_info_list, i++, strdup(msg->msginfo->inChannel));
  1302.     }
  1303.     
  1304.     ix = msg->reciplist;
  1305.     if (ix != NULL) ix = ix->next;
  1306.     while (ix != NULL) {
  1307.         /* make sure have enough space for next recip */
  1308.         if (i + 20 >= msg_info_list_size)
  1309.             resize_info_list(&msg_info_list, &msg_info_list_size);
  1310.  
  1311.         set_info_list(msg_info_list, i++, strdup(" "));
  1312.         set_info_list(msg_info_list, i++, strdup(" "));
  1313.  
  1314.         set_info_list(msg_info_list, i++, strdup("To"));
  1315.         str = (uk_order) ? reverse_adr(ix -> recipient) 
  1316.             : strdup(ix -> recipient);
  1317.         sprintf(buf, "%s (id %d)", str, ix->id);
  1318.         free(str);
  1319.         set_info_list(msg_info_list, i++, strdup(buf));
  1320.  
  1321.         if (ix->info != NULLCP) {
  1322.             set_info_list(msg_info_list, i++, strdup("Error Information"));
  1323.             set_info_list(msg_info_list, i++, strdup(ix->info));
  1324.         }
  1325.  
  1326.         if (ix->chansOutstanding == NULL) {
  1327.             set_info_list(msg_info_list, i++, strdup(" "));
  1328.             set_info_list(msg_info_list, i++, strdup("awaiting DRs"));
  1329.         } else {
  1330.             set_info_list(msg_info_list, i++, strdup("Remaining channels"));
  1331.             set_info_list(msg_info_list, i++, strdup(ix->chansOutstanding));
  1332.         }
  1333.  
  1334.         if (ix->status->cachedUntil != 0) {
  1335.             set_info_list(msg_info_list, i++, strdup("Delayed until"));
  1336.             str = time_t2RFC(ix->status->cachedUntil);
  1337.             set_info_list(msg_info_list, i++, str);
  1338.         }
  1339.  
  1340.         set_info_list(msg_info_list, i++, strdup("Status"));
  1341.         set_info_list(msg_info_list, i++,
  1342.                   strdup((ix->status->enabled == TRUE) ? "enabled" : "disabled"));
  1343.         
  1344.         if (ix->status->lastAttempt != 0) {
  1345.             set_info_list(msg_info_list, i++, strdup("Last attempt"));
  1346.             str = time_t2RFC(ix->status->lastAttempt);
  1347.             set_info_list(msg_info_list, i++, str);
  1348.         }
  1349.  
  1350.         if (ix->status->lastSuccess != 0) {
  1351.             set_info_list(msg_info_list, i++, strdup("Last success"));
  1352.             str = time_t2RFC(ix->status->lastSuccess);
  1353.             set_info_list(msg_info_list, i++, str);
  1354.         }
  1355.         ix = ix->next;
  1356.     }
  1357.     /* make sure have enough space for rest of info */
  1358.     if (i + 10 >= msg_info_list_size)
  1359.         resize_info_list(&msg_info_list, &msg_info_list_size);
  1360.  
  1361.     set_info_list(msg_info_list, i++, strdup(" "));
  1362.     set_info_list(msg_info_list, i++, strdup(" "));
  1363.  
  1364.     if (msg->msginfo->contenttype != NULLCP) {
  1365.         set_info_list(msg_info_list, i++, strdup("Content type"));
  1366.         set_info_list(msg_info_list, i++, strdup(msg->msginfo->contenttype));
  1367.     }
  1368.  
  1369.     if (msg->msginfo->eit != NULL) {
  1370.         set_info_list(msg_info_list, i++, strdup("Eits"));
  1371.         set_info_list(msg_info_list, i++, strdup(msg->msginfo->eit));
  1372.     }
  1373.  
  1374.     set_info_list(msg_info_list, i++, strdup("Age"));
  1375.     str = time_t2str(time((time_t *) 0) - msg->msginfo->age);
  1376.     set_info_list(msg_info_list, i++, str);
  1377.  
  1378.     if (msg->msginfo->expiryTime != 0) {
  1379.         set_info_list(msg_info_list, i++, strdup("Expiry time"));
  1380.         str = time_t2RFC(msg->msginfo->expiryTime);
  1381.         set_info_list(msg_info_list, i++, str);
  1382.     }
  1383.  
  1384.     if (msg->msginfo->deferredTime != 0) {
  1385.         set_info_list(msg_info_list, i++, strdup("Deferred until"));
  1386.         str = time_t2RFC(msg->msginfo->deferredTime);
  1387.         set_info_list(msg_info_list, i++, str);
  1388.     }
  1389.     
  1390.     set_info_list(msg_info_list, i++, strdup("Priority"));
  1391.     switch (msg->msginfo->priority) {
  1392.         case int_Qmgr_Priority_low:
  1393.         str = strdup("low");
  1394.         break;
  1395.         case int_Qmgr_Priority_normal:
  1396.         default:
  1397.         str = strdup("normal");
  1398.         break;
  1399.         case int_Qmgr_Priority_high:
  1400.         str = strdup("high");
  1401.         break;
  1402.     }
  1403.     set_info_list(msg_info_list, i++, str);
  1404.  
  1405.     if (msg->msginfo->errorCount != 0) {
  1406.         set_info_list(msg_info_list, i++, strdup("Number of errors"));
  1407.         str = itoa(msg->msginfo->errorCount);
  1408.         set_info_list(msg_info_list, i++, str);
  1409.     }
  1410.  
  1411.  
  1412.     XawListChange(msg_all_list,
  1413.               msg_info_list,
  1414.               i, 0, True);
  1415.  
  1416.     XtVaSetValues(msg_info,
  1417.           XtNlabel, "all",
  1418.           NULL);
  1419.  
  1420.     XtSetMappedWhenManaged(msg_all, True);
  1421.     XtSetMappedWhenManaged(msg_viewport, False);
  1422.     if ((font = msgFont(msg)) != NULL)
  1423.         XtVaSetValues(msg_info,
  1424.               XtNfont, font,
  1425.               NULL);
  1426.     msg_info_shown = TRUE;
  1427. }
  1428.  
  1429. msg_display_all()
  1430. {
  1431.     XtVaSetValues(msg_info,
  1432.           XtNlabel, "info",
  1433.           NULL);
  1434.     XtSetMappedWhenManaged(msg_viewport, True);
  1435.     XtSetMappedWhenManaged(msg_all, False);
  1436.     msg_info_shown = FALSE;
  1437. }
  1438.  
  1439. display_msgs()
  1440. {
  1441.     if (mode == control)
  1442.         control_display_msgs();
  1443. }
  1444.  
  1445. int display_empty_msg_list()
  1446. {
  1447.     int    i;
  1448.  
  1449.     for (i = 0; i < actual_nmsgs_present; i++) {
  1450.         msg_array[i].msg = NULL;
  1451.         XtSetMappedWhenManaged(msg_array[i].widget, False);
  1452.     }
  1453.     currentmsg = NULL;
  1454.     reset_label(msg_label);
  1455.     MtaToggle();
  1456.     MsgToggle();
  1457. }
  1458.  
  1459. int    control_msgs_ub = 10, 
  1460.     msgs_ub = True;
  1461. extern    Widget    msgs_showall;
  1462.  
  1463. control_display_msgs()
  1464. {
  1465.     int    i;
  1466.     char    *str;
  1467.     XFontStruct    *font;
  1468.     XtUnmanageChild(msgs);
  1469.     XawFormDoLayout(msgs, False);
  1470.  
  1471.     for (i = 0; i < actual_nmsgs_present; i++)
  1472.         XtSetMappedWhenManaged(msg_array[i].widget, False);
  1473.     resize_msg_array((msgs_ub == True && number_msgs > control_msgs_ub) ? control_msgs_ub : number_msgs);
  1474.  
  1475.     i = 0;
  1476.     while (i < num_msgs_displayed) {
  1477.         msg_array[i].msg = global_msg_list[i];
  1478.         str = create_msg_display_string(global_msg_list[i]);
  1479.         XtSetMappedWhenManaged(msg_array[i].widget, True);
  1480.         XtUnmanageChild(msg_array[i].widget);
  1481.         font = msgFont(msg_array[i].msg);
  1482.         XtVaSetValues(msg_array[i].widget,
  1483.               XtNlabel, str,
  1484.               XtNbackgroundPixmap,
  1485.               (font != NULL && font == disabledFont) ? backpixmap : ParentRelative,
  1486.               XtNborderColor, msgcolourOf(msg_array[i].msg),
  1487.               XtNborderWidth, msgborderOf(msg_array[i].msg),
  1488.               NULL);
  1489.         if (font != NULL)
  1490.             XtVaSetValues(msg_array[i].widget,
  1491.                   XtNfont, font,
  1492.                   NULL);
  1493.  
  1494.         XtManageChild(msg_array[i].widget);
  1495.         free(str);
  1496.         i++;
  1497.     }
  1498.     if (msgs_ub == True && num_msgs_displayed < number_msgs)
  1499.         XtSetMappedWhenManaged(msgs_showall, True);
  1500.     else
  1501.         XtSetMappedWhenManaged(msgs_showall, False);
  1502.  
  1503.     if (msg_info_shown == TRUE
  1504.         && currentmsg != NULL)
  1505.         msg_display_info(currentmsg);
  1506.     XawFormDoLayout(msgs, True);
  1507.     XtManageChild(msgs);
  1508. }
  1509.  
  1510. monitor_display_msgs()
  1511. {
  1512. }
  1513.  
  1514. char    *create_msg_header()
  1515. {
  1516.     /* takes from current msg */
  1517.     char    *str;
  1518.     char    buf[BUFSIZ];
  1519.     if (currentmsg == NULL)
  1520.         str = strdup("No current message");
  1521.     else {
  1522.         sprintf(buf, "Current msg : %s", 
  1523.             currentmsg->msginfo->queueid);
  1524.         str = strdup(buf);
  1525.     }
  1526.  
  1527.     return str;
  1528. }
  1529.  
  1530. resize_msg_array(num)
  1531. int    num;    /* new number of msgs */
  1532. {
  1533.     int    i = num;
  1534. /*    if (control_msgs_ub < actual_nmsgs_present)*/
  1535.         
  1536.     while (i < actual_nmsgs_present) {
  1537.         XtSetMappedWhenManaged(msg_array[i].widget, False);
  1538.         XtDestroyWidget(msg_array[i].widget);
  1539.         i++;
  1540.     }
  1541.  
  1542.     if (num == 0) {
  1543.         if (msg_array != NULL) {
  1544.             free ((char *) msg_array);
  1545.             msg_array = NULL;
  1546.         }
  1547.     } else if (actual_nmsgs_present == 0)
  1548.         msg_array = (struct msg_disp_struct *)
  1549.             calloc((unsigned int) num,
  1550.                    sizeof(struct msg_disp_struct));
  1551.     else if (actual_nmsgs_present != num)
  1552.         msg_array = (struct msg_disp_struct *)
  1553.             realloc((char *) msg_array,
  1554.                  (unsigned int) (num * sizeof(struct msg_disp_struct)));
  1555.  
  1556.     while (actual_nmsgs_present < num) {
  1557.         msg_array[actual_nmsgs_present].msg = NULL;
  1558.         msg_array[actual_nmsgs_present].widget =
  1559.             XtVaCreateManagedWidget(NULL,
  1560.                      labelWidgetClass,
  1561.                      msgs,
  1562.                      XtNfromVert, (actual_nmsgs_present == 0) ? NULL : msg_array[actual_nmsgs_present-1].widget,
  1563.                      XtNfromHoriz,    NULL,
  1564.                      XtNresizable,    TRUE,
  1565.                      XtNborderWidth,    2,
  1566.                      XtNleft,    XtChainLeft,
  1567.                      XtNright,    XtChainLeft,
  1568.                      XtNtop,    XtChainTop,
  1569.                      XtNbottom,    XtChainTop,
  1570.                      NULL);
  1571.         actual_nmsgs_present++;
  1572.     }
  1573.     actual_nmsgs_present = num;
  1574.     num_msgs_displayed = num;
  1575. }
  1576.  
  1577. static char    *create_msg_display_string(msg)
  1578. struct msg_struct    *msg;
  1579. {
  1580.     char    str[BUFSIZ];
  1581.     char    *ch1, *ch2;
  1582.  
  1583.     if (msg->reciplist == NULL
  1584.         || msg->reciplist->next == NULL)
  1585.         /* delivery report */
  1586.         sprintf(str,"dr (%s) to %s",
  1587.             msg->msginfo->queueid,
  1588.             msg->msginfo->originator);
  1589.     else {
  1590.         struct recip    *ix = msg->reciplist;
  1591.         int        found = 0;
  1592.  
  1593.         while (ix != NULL && found == 0) {
  1594.             if (ix->actChan != NULL 
  1595.                 && currentchan != NULL 
  1596.                 && strcmp(ix->actChan, 
  1597.                       currentchan->channelname) == 0) {
  1598.                 /* channel matches */
  1599.                 if (is_loc_chan(currentchan) == TRUE) { 
  1600.                     if (ix->recipient && currentmta
  1601.                         && strcmp(ix->recipient, currentmta->mta) == 0)
  1602.                         found = 1;
  1603.                 } else if (ix->mta != NULL 
  1604.                        && currentmta != NULL
  1605.                        && strcmp(ix->mta, 
  1606.                              currentmta->mta) == 0)
  1607.                     /* mta matches */
  1608.                     found = 1;
  1609.             }
  1610.             if (found == 0)
  1611.                 ix = ix->next;
  1612.         }
  1613.         if (ix != NULL && ix->id == 0) {
  1614.             /* delivery report ? */
  1615.             ch1 = (uk_order) ? reverse_adr(ix -> recipient)
  1616.                 : ix -> recipient;
  1617.             sprintf(str, "dr (%s) to %s",
  1618.                 msg->msginfo->queueid,
  1619.                 ch1);
  1620.             if (uk_order && ch1 != ix -> recipient) free(ch1);
  1621.         } else {
  1622.             if (ix == NULL) ix = msg->reciplist->next;
  1623.  
  1624.             ch1 = (uk_order) ? reverse_adr(ix -> recipient) : ix -> recipient;
  1625.             ch2 = (uk_order) ? reverse_adr(msg->msginfo->originator) : msg->msginfo->originator;
  1626.  
  1627.             sprintf(str, "%s to %s from %s",
  1628.                 msg->msginfo->queueid,
  1629.                 ch1, ch2);
  1630.             if (uk_order) {
  1631.                 if (ch1 != ix -> recipient) free(ch1);
  1632.                 if (ch2 != msg->msginfo->originator) free(ch2);
  1633.             }
  1634.         }
  1635.     }
  1636.  
  1637.     return strdup(str);
  1638. }
  1639.  
  1640. reset_label(hdr)
  1641. Widget    hdr;
  1642. {
  1643.     char *str = NULL;
  1644.     XFontStruct    *font = normalFont;
  1645.     if (hdr == channel_label) {
  1646.         str = create_channel_header();
  1647.         font = chanFont(currentchan);
  1648.     } else if (hdr == mta_label) {
  1649.         str = create_mta_header();
  1650.         font = mtaFont(currentmta);
  1651.     } else if (hdr == msg_label) {
  1652.         str = create_msg_header();
  1653.         font = msgFont(currentmsg);
  1654.     }
  1655.     XtVaSetValues(hdr,
  1656.           XtNlabel, str,
  1657.           NULL);
  1658.     if (font != NULL)
  1659.         XtVaSetValues(hdr,
  1660.               XtNfont, font,
  1661.               NULL);
  1662.  
  1663.     if (str) free(str);
  1664. }    
  1665.  
  1666. /*   */
  1667. extern Widget    connect_command,
  1668.         refresh_command;
  1669. extern struct tailor *tailors;
  1670. extern void    tailor_free();
  1671.  
  1672. ResetForDisconnect()
  1673. {
  1674.     /* change disconnect to connect */
  1675.     XtVaSetValues(connect_command,
  1676.           XtNlabel, "connect",
  1677.           NULL);
  1678.     XtVaSetValues(refresh_command,
  1679.           XtNlabel, "refresh",
  1680.           NULL);
  1681.     if (tailors) {
  1682.         tailor_free(tailors);
  1683.         tailors = NULL;
  1684.     }
  1685.     MapButtons(False);
  1686.     MapVolume(False);
  1687.     undisplay_time_label();
  1688.  
  1689.     if (connectState == connected)
  1690.         clear_displays();
  1691.     if (Qinformation != NULLCP) {
  1692.         free(Qinformation);
  1693.         Qinformation = NULLCP;
  1694.     }
  1695.     if (Qversion != NULLCP) {
  1696.         free(Qversion);
  1697.         Qversion = NULLCP;
  1698.         XtVaSetValues(qversion,
  1699.               XtNlabel,    "???",
  1700.               NULL);
  1701.     }
  1702. }
  1703.  
  1704. clear_displays()
  1705. {
  1706.     /* unmap all displays */
  1707.     /* deal with channel display */
  1708.     clear_monitor();
  1709.     clear_channel_display();
  1710.     clear_control();
  1711.     
  1712. }
  1713.  
  1714. clear_monitor()
  1715. {
  1716.     int     i = 0,
  1717.         j = 0;
  1718.     XawFormDoLayout(monitor_form, False);
  1719.     if (display_list != NULL) {
  1720.         while (i < num_channels) {
  1721.             if (display_list[i] != NULL) {
  1722.                 if (display_list[i]->form)
  1723.                     XawFormDoLayout(display_list[i]->form, False);        
  1724.                 if (display_list[i]->box)
  1725.                     XawFormDoLayout(display_list[i]->box, False);
  1726.                 if (display_list[i]->chan != NULL) {
  1727.                     XtDestroyWidget(display_list[i]->chan);
  1728.                     j = 0;
  1729.                     while (j < display_list[i] -> num_allocd
  1730.                            && display_list[i]->mtas[j] != NULL) {
  1731.                         if (display_list[i]->mtas[j]->widget != NULL)
  1732.                             XtDestroyWidget(display_list[i]->mtas[j]->widget);
  1733.                         free((char *) display_list[i]->mtas[j]);
  1734.                         j++;
  1735.                     }
  1736.                     if (display_list[i]->mtas)
  1737.                         free((char *) display_list[i]->mtas);
  1738.                 }
  1739.                 if (display_list[i]->box != NULL)
  1740.                     XtDestroyWidget(display_list[i]->box);
  1741.                 if (display_list[i]->form != NULL)
  1742.                     XtDestroyWidget(display_list[i]->form);
  1743.             }
  1744.         free((char *) display_list[i]);
  1745.         i++;
  1746.         }
  1747.         free((char *) display_list);
  1748.         display_list = NULL;
  1749.     }
  1750.     XawFormDoLayout(monitor_form, True);
  1751. }
  1752.  
  1753. clear_control()
  1754. {
  1755.     /* destructive clear removing channel, mta, msg displays */
  1756.     /* and freeing globallist */
  1757.     clear_mta_display();
  1758.     clear_msg_display();
  1759. }
  1760.  
  1761. clear_channel_display()
  1762. {
  1763.     int    i;
  1764.     free_channel_list();
  1765.     currentchan = NULL;
  1766.     resize_chan_array(0);
  1767.     reset_label(channel_label);
  1768.     ChanToggle();
  1769.     for (i = 0; i < actual_nchans_present; i++) {
  1770.         if (channel_array[i] != NULL) 
  1771.             XtSetMappedWhenManaged(channel_array[i], False);
  1772.     }
  1773. }
  1774.  
  1775. clear_mta_display()
  1776. {
  1777.     int    i;
  1778.  
  1779.     XtSetMappedWhenManaged(mta_viewport, False);
  1780.     XtSetMappedWhenManaged(mtas, False);
  1781.     XtUnmanageChild(mtas);
  1782.     resize_mta_array(0);
  1783.     XtManageChild(mtas);
  1784.     XtSetMappedWhenManaged(mtas, True);
  1785.     XtSetMappedWhenManaged(mta_viewport, True);
  1786.     currentmta = NULL;
  1787.     read_currentmta = 0;
  1788.     reset_label(mta_label);
  1789.     MtaToggle();
  1790.     for (i = 0; i < actual_nmtas_present; i++) {
  1791.         if (mta_array[i].widget != NULL) 
  1792.             XtSetMappedWhenManaged(mta_array[i].widget, False);
  1793.     }
  1794. }
  1795.  
  1796. clear_msg_display()
  1797. {
  1798.     int    i;
  1799.  
  1800.     resize_msg_array(0);
  1801.     currentmsg = NULL;
  1802.     reset_label(msg_label);
  1803.     MsgToggle();
  1804.     if (msg_info_shown == TRUE)
  1805.         msg_display_all();
  1806.     for (i = 0; i < actual_nmsgs_present; i++) {
  1807.         if (msg_array[i].widget != NULL)
  1808.             XtSetMappedWhenManaged(msg_array[i].widget, False);
  1809.     }
  1810. }
  1811.  
  1812. void ChanToggle()
  1813. {
  1814.     if (chan_info_shown == TRUE)
  1815.         chan_display_all();
  1816. }
  1817.  
  1818. void MtaToggle()
  1819. {
  1820.     if (mta_info_shown == TRUE)
  1821.         mta_display_all();
  1822. }
  1823.  
  1824. void MsgToggle()
  1825. {
  1826.     if (msg_info_shown == TRUE)
  1827.         msg_display_all();
  1828. }
  1829.  
  1830. toggle_info_displays()
  1831. {
  1832.     ChanToggle();
  1833.     MtaToggle();
  1834.     MsgToggle();
  1835. }
  1836.  
  1837. /*   */
  1838. textdisplay(tuple, str)
  1839. Popup_tuple    *tuple;
  1840. char    *str;
  1841. {
  1842.     XtVaSetValues (tuple -> text, XtNstring, str == NULLCP ? "" : str, 0);
  1843. }
  1844.  
  1845. extern Widget    top;
  1846. terminate_display()
  1847. {
  1848.     XtDestroyWidget(top);
  1849. /*    XtDestroyWidget(popup);*/
  1850. }
  1851.  
  1852. update_channel_from_mtas(chan, nmsgs, ndrs, nmtas, volume)
  1853. struct chan_struct    *chan;
  1854. int            nmsgs,
  1855.               ndrs,
  1856.             nmtas,
  1857.             volume;
  1858. {
  1859.     int    changed = FALSE;
  1860.     
  1861.     if (chan -> numberMessages != nmsgs) {
  1862.         if (compat)
  1863.             total_number_messages 
  1864.                 += nmsgs - chan -> numberMessages;
  1865.         chan -> numberMessages = nmsgs;
  1866.         changed = TRUE;
  1867.     }
  1868.     
  1869.     if (chan -> numberReports != ndrs) {
  1870.         if (compat)
  1871.             total_number_reports += ndrs - chan -> numberReports;
  1872.         chan -> numberReports = ndrs;
  1873.         changed = TRUE;
  1874.     }
  1875.  
  1876.     if (chan -> num_mtas != nmtas) {
  1877.         chan -> num_mtas = nmtas;
  1878.         changed = TRUE;
  1879.     }
  1880.     if (chan -> volumeMessages != volume) {
  1881.         if (compat)
  1882.             total_volume += volume - chan -> volumeMessages;
  1883.         chan -> volumeMessages = volume;
  1884.         changed = TRUE;
  1885.     }
  1886.  
  1887.     if (chan->given_num_mtas != chan -> num_mtas) {
  1888.         chan -> given_num_mtas = chan->num_mtas;
  1889.         changed = TRUE;
  1890.     }
  1891.  
  1892.  
  1893.     if (changed == TRUE) {
  1894.         redisplay_channel(chan);
  1895.         if (compat)
  1896.             display_totals();
  1897.     }
  1898. }
  1899.  
  1900. static void redisplay_channel(chan)
  1901. struct chan_struct    *chan;
  1902. {
  1903.     int    i = 0;
  1904.     char    *str;
  1905.  
  1906.     /* do control display */
  1907.     while (i < num_channels && globallist[i] != chan)
  1908.         i++;
  1909.  
  1910.     if (i < num_channels) {
  1911.         str = create_channel_display_string(globallist[i]);
  1912.         XtVaSetValues(channel_array[i],
  1913.               XtNlabel, str,
  1914.               XtNborderColor, chancolourOf(globallist[i]),
  1915.               XtNborderWidth, chanborderOf(globallist[i]),
  1916.               XtNbackgroundPixmap,
  1917.               (globallist[i]->status->enabled == FALSE) ? backpixmap : ParentRelative,
  1918.               NULL);
  1919.         free(str);
  1920.     }
  1921.  
  1922.     if (mode == monitor) {
  1923.         /* do monitor display */
  1924.         str = create_channel_monitor_string(chan);
  1925.         XtVaSetValues(display_list[chan->display_num] ->  chan,
  1926.               XtNlabel, str,
  1927.               XtNborderColor, chancolourOf(chan),
  1928.               XtNborderWidth, chanborderOf(chan),
  1929.               XtNbackgroundPixmap, (chan->status->enabled == FALSE) ? backpixmap : ParentRelative,
  1930.               NULL);
  1931.         free(str);
  1932.     }
  1933. }
  1934.  
  1935. static char    *time_t2str(in)
  1936. time_t  in;
  1937. {
  1938.     char    buf[BUFSIZ];
  1939.     time_t    result;
  1940.     buf[0] = '\0';
  1941.     
  1942.     if (in < 0)
  1943.         return strdup("still in the womb");
  1944.  
  1945.     if ((result = in / (60 * 60 * 24)) != 0) {
  1946.         sprintf(buf, "%d day%s",
  1947.             result,
  1948.             (result == 1) ? "" : "s");
  1949.         in = in % (60 * 60 * 24);
  1950.     }
  1951.  
  1952.     if ((result = in / (60 * 60)) != 0) {
  1953.         sprintf(buf, 
  1954.             (buf[0] == '\0') ? "%s%d hr%s" : "%s %d hr%s",
  1955.             buf, 
  1956.             result,
  1957.             (result == 1) ? "" : "s");
  1958.         in = in % (60 * 60);
  1959.     }
  1960.     if ((result = in / 60) != 0) {
  1961.         sprintf(buf, 
  1962.             (buf[0] == '\0') ? "%s%d min%s" : "%s %d min%s",
  1963.             buf, 
  1964.             result,
  1965.             (result == 1) ? "" : "s");
  1966.         in = in % 60;
  1967.     }
  1968.  
  1969.     if (buf[0] == '\0' && in != 0)
  1970.         sprintf(buf, "%d sec%s", 
  1971.             in,
  1972.             (in == 1) ? "" : "s");
  1973.     if (buf[0] == '\0')
  1974.         sprintf(buf, "just born");
  1975.     return strdup(buf);
  1976. }
  1977.  
  1978. static void    resize_info_list(plist, psize)
  1979. char        ***plist;
  1980. int        *psize;
  1981. {
  1982.     if (*psize == 0) {
  1983.         *psize += BUFSIZ;
  1984.         *plist = (char **) calloc(*psize, sizeof(char *));
  1985.     } else {
  1986.         *psize += BUFSIZ;
  1987.         *plist = (char **) realloc(*plist, 
  1988.                        (unsigned) (*psize) * sizeof(char *));
  1989.     }
  1990. }
  1991.